import java.util.ArrayList;
import java.lang.StringBuilder;

/**
 * Inmplementation of arrays in the Graphr Language
 * @author Paul Dix
 */
public class GraphrArray extends GraphrDataType implements GraphrCollection {
	//Variable declaration
	private ArrayList<GraphrDataType> array;
  
	/**
	 * Constructs an empty GraphrArray
	 */
	public GraphrArray() {
		this.array = new ArrayList<GraphrDataType>();
	}
	
	public GraphrDataType add(GraphrDataType rVal) {
	  push(rVal);
	  return this;
	}
	
	/**
	 * Returns the array list of this GraphrArray object.
	 * @returns the array list of this GraphrArray object.
	 */
	public ArrayList<GraphrDataType> getArray() {
		return this.array;
	}
	
	/**
	 * Returns a string representation of the object.
	 * @returns a string representation of the object.
	 */
	public String toString() {
		if (this.array.isEmpty()) {
			return "[ ]";
		}
		StringBuilder returnString = new StringBuilder();
		returnString.append("[ ");
		for (int i = 0; i < this.array.size() - 1; i++) {
			returnString.append(this.array.get(i).toString() + ", ");
		}
		returnString.append(this.array.get(this.array.size() - 1).toString() + " ]");
		return returnString.toString();
	}
	
	/**
	 * Puts the GraphrDataType val into the array.
	 * @param val - value to be added to the array.
	 */
	public void push(GraphrDataType val) {
		this.array.add(val);
	}
	
	/**
	 * Returns the GraphrDataType at the location provided by key.
	 * @param key -the key whose associated value is to be returned.
	 * @returns GraphrDataType at the location provided by key.
	 */
	public GraphrDataType getValueAt(GraphrDataType key) {
		return this.array.get(((GraphrNumber)key).toInt());
	}
	
	/**
	 * Associates the specified value with the specified key in this array.
	 * @param key - key with which the specified value is to be associated.
     	 * @param value - value to be associated with the specified key.
	 */
	public void setValueAt(GraphrDataType key, GraphrDataType value) {
		this.array.set(((GraphrNumber)key).toInt(), value);
	}
	
	/**
	 * Returns <b>true</b> if this array contains the specified key.
	 * @param key - the key whose presence in this associative array is to be tested.
	 * @returns <b>true</b> if this array contains the specified key; <b>false</b> otherwise.
	 */	
	public boolean contains(GraphrDataType key) {
		return this.array.contains(key);
	}
	
	/**
	 * Returns <b>true</b> if this array equals rVal; <b>false</b> otherwise.
	 * @param rVal - the GraphrDataType to compare with.
	 * @returns <b>true</b> if this array equals rVal; <b>false</b> otherwise.
	 */	
	public GraphrBoolean equals(GraphrDataType rVal) {
	  if (this.getClass() == rVal.getClass()) {
	    return new GraphrBoolean(this.array.equals(((GraphrArray)rVal).getArray()));
	  }
	  else {
	    return new GraphrBoolean(false);
	  }
	}
}